﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Apex.Networking.Common;
using Apex.Networking.Server;

namespace Aster
{
    public class ControllerTuple
    {
        public IController Controller { get; set; }
        public ServerConfiguration Configuration { get; set; }
    }

    public class ServerController
    {
        private const string ServerPath = "Servers";

        private List<IServer> serverList;
        private Dictionary<string, ControllerTuple> controllers;

        public ServerController()
        {
            serverList = new List<IServer>();
            controllers = new Dictionary<string, ControllerTuple>();
            Load();
            Start();
        }

        private void Start()
        {
            foreach (var x in serverList)
            {
                x.StartServer();
            }

            foreach (var y in controllers)
            {
                var tup = y.Value;

            }
        }

        private void Load()
        {
            var servers = Directory.EnumerateFiles(ServerPath);
            var errors = new List<Exception>();

            foreach (var x in servers)
            {
                Assembly sr = Assembly.LoadFrom(x);


                var server = sr.ExportedTypes.FirstOrDefault(d => d.BaseType == typeof(IServer));
                var controller = sr.ExportedTypes.FirstOrDefault(d => d.BaseType == typeof(IController));

                if (server != null && controller != null)
                {
                    var ex = new InvalidOperationException(string.Format("Assembly {0} contains both a type that inherits IServer and a type that inherits IController. Only one of these types is allowed", sr.FullName));
                    errors.Add(ex);
                }

                if (server != null)
                {
                    var srv = (IServer)Activator.CreateInstance(server);
                    serverList.Add(srv);
                }

                if (controller != null)
                {
                    var contrl = (IController)Activator.CreateInstance(controller);
                    var configType = sr.ExportedTypes.FirstOrDefault(d => d.BaseType == typeof(ServerConfiguration));
                    var serverConfig = (ServerConfiguration)Activator.CreateInstance(configType);

                    controllers.Add(sr.FullName, new ControllerTuple() { Configuration = serverConfig, Controller = contrl });
                }

            }

            foreach (var x in errors)
            {
                Console.WriteLine();
                Console.WriteLine(x);
                Console.WriteLine();
            }
        }
    }
}
